package pcb.views.sharedAssets.menu
{
	import flash.display.MovieClip;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import pcb.views.uievents.TreeNodeEvent;
	import com.intel.utils.TextRender;

	
	/**
	 * ...
	 * @author ...
	 */
	public class TreeNode extends EventDispatcher
	{
		
		public static const OPEN_NODE:String = "openNode";
		public static const OPENING_NODE:String = "openingNode";
		public static const CLOSED_NODE:String = "closedNode";
		
		public static const indent:int = 10;
		private static const iconSpace:Number = 15;
		
		public static const LEVEL_MODULE:Number = 0;
		public static const LEVEL_SECTION:Number = 1;
		public static const LEVEL_LESSON:Number = 2;
		
		
		
		private var _label:String;
		private var _id:String;	
		private var _children:Vector.<TreeNode>;
		private var _nodeLevel:int;
		private var _index:int;
		private var _nodeType:String;
		private var _nodeState:String;
		private var _target:MovieClip;
		private var mcNode:MovieClip;
		private var txt:TextField;
		private var _parent:*;
		private var txtFmt:TextFormat;
		
		public function TreeNode(in_target:MovieClip, in_parent:*, in_label:String, in_id:String, in_level:int, in_type:String, in_index:Number, in_children:XMLList, in_state:String = TreeNode.CLOSED_NODE) 
		{
			super();
			_target = in_target;			
			parent = in_parent;
			label = in_label;
			id = in_id;
			nodeLevel = in_level;
			nodeType = in_type;		
			_index = in_index;
			nodeState = in_state;
			
			//switch here on type
			mcNode = getMovieClip();
			
			setIconState();
			createFormatting();
			createLabel();
			addListeners();
			addChildren(in_children);
		}
		
		private function setIconState():void
		{
			if (nodeType != "" && nodeLevel == TreeNode.LEVEL_LESSON) {				
				MovieClip(mcNode.getChildByName("mcIcon")).gotoAndStop(nodeType);
			}
			
		}
		
		private function getMovieClip():MovieClip
		{
			var mc:MovieClip;
			if (nodeLevel == 0) {
				mc = new ModuleNodeMC();
			} else if (nodeLevel == 1) {
				mc = new SectionNodeMC();
			} else if (nodeLevel == 2) {
				mc = new LessonNodeMC();
			} 
			return mc;
		}
		
		private function addListeners():void
		{
			var mcBut:MovieClip = mcNode.getChildByName("mcButton") as MovieClip;
			mcBut.mouseEnabled = true;
			mcBut.mouseChildren = false;
			mcBut.buttonMode = true;
			mcBut.useHandCursor = true;
			
			mcBut.addEventListener(MouseEvent.CLICK, nodeClicked);
			//need to do mouse overs and outs 
		}
		
		private function removeListeners():void
		{
			var mcBut:MovieClip = mcNode.getChildByName("mcButton") as MovieClip;
			mcBut.mouseEnabled = false;
			mcBut.buttonMode = false;
			mcBut.useHandCursor = false;
			
			mcBut.removeEventListener(MouseEvent.CLICK, nodeClicked);
			//need to do mouse overs and outs 
		}

		
		private function nodeClicked(e:MouseEvent):void 
		{			
			if (nodeState == TreeNode.CLOSED_NODE) {
				nodeState = TreeNode.OPENING_NODE;
				
			} else if (hasChildren()) {				
				nodeState = TreeNode.CLOSED_NODE;				
			}
			nofifyClicked();
		}
		
		public function select():void {
			nodeState = TreeNode.OPENING_NODE;
			nofifyClicked();
		}
		
		private function nofifyClicked():void
		{
			dispatchEvent(new TreeNodeEvent(TreeNodeEvent.CLICKED, this));
		}
		
		public function hasNextNode(node:TreeNode):Boolean {
			if (node.index == _children.length - 1) {
				return false;
			}
			return true;
		}
		
		public function hasPrevNode(node:TreeNode):Boolean {
			if (node.index > 0) {
				return true;
			}
			return false;
		}
		
		public function getNextNode(node:TreeNode):TreeNode {
			return(_children[node.index + 1]);
		}
		
		public function getPrevNode(node:TreeNode):TreeNode {
			return(_children[node.index - 1]);
		}
		
		private function childClicked(e:TreeNodeEvent):void 
		{
			dispatchEvent(e);
		}
		
		private function createFormatting():void 
		{
			if (nodeLevel == TreeNode.LEVEL_LESSON) {
				txtFmt = new TextFormat("_sans", 12, 0xffffff,true);
			}else {
				txtFmt = new TextFormat("_sans", 12, 0x000000,true);
			}			
		}
		private function createLabel():void
		{	
			txt = new TextField();
			//txt.border = true;			
			txt.selectable = false;
			
			txt.width = (mcNode.width - (nodeLevel * TreeNode.indent)) - iconSpace;
			
			if(com.intel.utils.TextRender.iBidiLevel == 1) {
				txt.x = 0;
			} else {
				txt.x = iconSpace + nodeLevel * TreeNode.indent;
			}
			
			txt.y = 0;
			
			txt.multiline = true;
			txt.wordWrap = true;
			txt.autoSize = "left";
			txt.mouseEnabled = false;
			
			//get text render to draw
			txt.text = label;
			txt.setTextFormat(txtFmt);
			mcNode.addChild(txt);
			
			TextRender.createLabel(txt, label);
			
			resizeNode();
		}
		
		private function resizeNode():void
		{
			var mcBut:MovieClip = mcNode.getChildByName("mcButton") as MovieClip;
			var mcBack:MovieClip = mcNode.getChildByName("mcBack") as MovieClip;
			mcBut.height = mcBack.height = txt.textHeight + 5;
		}
		
		private function addChildren(data:XMLList):void 
		{
			_children = new Vector.<TreeNode>();
			for each(var node:XML in data) {
				var child:TreeNode = new TreeNode(mcNode, this, node.@label, node.@id, nodeLevel + 1, node.@type, _children.length, node.children());
				child.addEventListener(TreeNodeEvent.CLICKED, childClicked);
				_children.push(child);
			}
		}
		
		private function drawChildren(selectedNode:TreeNode, closeOthers:Boolean):void
		{
			for each (var childNode:TreeNode in _children) 
			{
				childNode.draw(selectedNode, closeOthers);
			}
		}
		
		private function removeChildNodes():void
		{
			for each (var childNode:TreeNode in _children) 
			{
				childNode.removeNode();
			}
		}		
		
		private function closeChildren():void
		{
			for each (var childNode:TreeNode in _children) 
			{
				childNode.nodeState = TreeNode.CLOSED_NODE;
			}
		}
		
		
		private function getNodeOnThisLevel(selectedNode:TreeNode):TreeNode {			
			if (selectedNode == null || selectedNode.nodeLevel < nodeLevel) {
				return null;
			}		
			
			if (selectedNode.nodeLevel == nodeLevel) {
				return selectedNode;
			} else if (selectedNode.parent.nodeLevel == nodeLevel) {
				return selectedNode.parent;
			} else {
				return selectedNode.parent.parent;
			}			
		}
		
		private function getChildByIndex(index:Number):TreeNode 
		{
			return _children[index];
		}
		
		
		public function draw(selectedNode:TreeNode, closeOthers:Boolean):void
		{			
			var openNode:TreeNode = getNodeOnThisLevel(selectedNode);
			
			if (nodeState == TreeNode.OPENING_NODE) {
				nodeState = TreeNode.OPEN_NODE;
			}
			
			if (openNode != null && closeOthers) {
				if (openNode != this) {
					nodeState = TreeNode.CLOSED_NODE;
				}
			}
			
			if (parent.nodeState == TreeNode.OPEN_NODE) {
				
				if(_index == 0) {
					mcNode.y = parent.getHeight();					
				} else {
					mcNode.y = parent.getPrevChildYPos(_index);
				}				
				_target.addChild(mcNode);
			} else {
				closeChildren();				
			}
			
			if (nodeState == TreeNode.OPEN_NODE) {
				mcNode.gotoAndStop("open");
				if (mcNode.lessonSelectedBG) {
					mcNode.lessonSelectedBG.height = mcNode.height;
				}
			} else {
				mcNode.gotoAndStop("closed");
			}
			
			drawChildren(selectedNode, closeOthers);
		}
		
		
		public function getHeight():Number
		{
			return mcNode.height;
		}
		
		
		public function nodeEndYPos():Number
		{
			return mcNode.y + mcNode.height;
		}
		
		public function getPrevChildYPos(childIndex:int):Number {
			if (childIndex > 0) {
				return _children[childIndex - 1].nodeEndYPos();
			} else {
				return nodeEndYPos();
			}
		}
		
		public function removeNode():void
		{
			if (_target.getChildByName(mcNode.name) != null) _target.removeChild(mcNode);
			
			removeChildNodes();
		}
		
		public function hasChildren():Boolean {
			return (_children.length > 0);
		}
		
		public function get label():String { return _label; }
		
		public function set label(value:String):void 
		{
			_label = value;
		}
		
		public function get id():String { 
			if (_id == "") {
				return null;
			}
			return _id; 
		}
		
		public function set id(value:String):void 
		{
			_id = value;
		}
		
		public function get nodeLevel():int { return _nodeLevel; }
		
		public function set nodeLevel(value:int):void 
		{
			_nodeLevel = value;
		}
		
		public function get nodeType():String { return _nodeType; }
		
		public function set nodeType(value:String):void 
		{
			_nodeType = value;
		}
		
		public function get nodeState():String { return _nodeState; }
		
		public function set nodeState(value:String):void 
		{
			_nodeState = value;
			if (value == TreeNode.OPENING_NODE && parent is TreeNode) {
				TreeNode(parent).nodeState = TreeNode.OPENING_NODE;
			}
			
		}
		
		public function get parent():* { return _parent; }
		
		public function set parent(value:*):void 
		{
			_parent = value;
		}
		
		public function get index():int { return _index; }		
		
		public function get firstChild():TreeNode 
		{
			return getChildByIndex(0);
		}
		
		public function get lastChild():TreeNode 
		{
			return getChildByIndex(_children.length - 1);
		}
		
		public function set enabled(value:Boolean):void { 
			if (hasChildren()) {
				for each (var childNode:TreeNode in _children) 
				{
					childNode.enabled = value;
				}
			}
			
			if (value) {
				addListeners();
			} else {
				removeListeners();
			}
			
		}
	}	
}